from typing import *
from PyQt6.QtWidgets import *
from PyQt6.QtCore import Qt
import ramda as R

def ux_expend_x(me:QWidget) -> QWidget:
    sp = me.sizePolicy()
    sp.setHorizontalPolicy(QSizePolicy.Policy.MinimumExpanding)
    me.setSizePolicy(sp)
    return me

def ux_expend_y(me:QWidget) -> QWidget:
    sp = me.sizePolicy()
    sp.setVerticalPolicy(QSizePolicy.Policy.MinimumExpanding)
    me.setSizePolicy(sp)
    return me

def ux_fix_layout(me:QLayout) -> QLayout:
    me.setSpacing(0)
    me.setContentsMargins(0,0,0,0)
    return me

def ux_row_layout(parent:QWidget=None) -> QVBoxLayout:
    return ux_fix_layout(QVBoxLayout(parent))

def ux_column_layout(parent:QWidget=None) -> QHBoxLayout:
    return ux_fix_layout(QHBoxLayout(parent))

def ux_group_box(title:str, align:Qt.AlignmentFlag=Qt.AlignmentFlag.AlignCenter, parent:QWidget = None) -> QGroupBox:
    me = QGroupBox(title, parent)
    me.setAlignment(align)
    return me

def ux_style_widget(me:QWidget, id:str) -> QWidget:
    if isinstance(id,str):
        assert(len(id) > 0)
        me.setObjectName(id)
    return me

def ux_label(text:str, id:str=None, parent:QWidget=None) -> QLabel:
    me:QLabel = ux_style_widget(QLabel(parent), id)
    me.setText(text)
    return me

def ux_pushbutton(text:str, id:str=None, on_click:Callable[[],None]=None, parent:QWidget=None) -> QPushButton:
    me:QPushButton = ux_style_widget(QPushButton(parent), id)
    me.setText(text)
    me.setCursor(Qt.CursorShape.PointingHandCursor)
    if callable(on_click):
        me.clicked.connect(on_click)
    return me

def ux_checkbutton(text:str, id:str=None, on_changed:Callable[[],None]=None, parent:QWidget=None) -> QCheckBox:
    me:QCheckBox = ux_style_widget(QCheckBox(text, parent), id)
    if callable(on_changed):
        me.stateChanged.connect(on_changed)
    return me

def ux_radiobutton(text:str, id:str=None, on_toggled:Callable[[],None]=None, parent:QWidget=None) -> QRadioButton:
    me:QRadioButton = ux_style_widget(QRadioButton(text, parent), id)
    if callable(on_toggled):
        me.toggled.connect(on_toggled)
    return me

def ux_slider(orient:Qt.Orientation, value_min:int=0, value_max:int=1, value_init:int=0, value_step:int=1, on_changed:Callable[[],None]=None, id:str=None, parent:QWidget=None) -> QSlider:
    me:QSlider = ux_style_widget(QSlider(orient), id)
    me.setMinimum(value_min)
    me.setMaximum(value_max)
    me.setSingleStep(value_step)
    me.setValue(R.clamp(value_min, value_max, value_init))
    if callable(on_changed):
        me.valueChanged.connect(on_changed)
    return me

def ux_slider_h(value_min:int=0, value_max:int=1, value_init:int=0, value_step:int=1, on_changed:Callable[[],None]=None, id:str=None, parent:QWidget=None) -> QSlider:
    return ux_slider(Qt.Orientation.Horizontal, value_min, value_max, value_init, value_step, on_changed, id, parent)

def ux_slider_v(value_min:int=0, value_max:int=1, value_init:int=0, value_step:int=1, on_changed:Callable[[],None]=None, id:str=None, parent:QWidget=None) -> QSlider:
    return ux_slider(Qt.Orientation.Vertical, value_min, value_max, value_init, value_step, on_changed, id, parent)

def ux_combobox(items:Iterable[Any], init_val:Any=None, id:str=None, on_select:Callable[[],None]=None, parent:QWidget=None) -> QComboBox:
    me:QComboBox = ux_style_widget(QComboBox(parent), id)
    init_select = 0
    cur = 0
    for val,show in items:
        if val == init_val: init_select = cur
        me.addItem(show, val)
        cur += 1
    if init_select < me.count():
        me.setCurrentIndex(init_select)
    if callable(on_select):
        me.currentIndexChanged.connect(on_select)
    return me
